#include "../../include/mesh/mesh.hpp"
#include "../../include/device/device.hpp"

#include <Windows.h>

#include <fstream>
#include <sstream>
#include <tuple>


using namespace DirectX;
using namespace std;

namespace SoftEngine{
    DotMatrix::DotMatrix():name(""),vertex(),position(0.0f,0.0f,0.0f),rotation(0.0f,0.0f,0.0f){}
    DotMatrix::DotMatrix(string dotMatrixName,int count,XMFLOAT3 position):name(dotMatrixName),vertex(count),position(position),rotation(0.0f,0.0f,0.0f){}
    DotMatrix::DotMatrix(string dotMatrixName,int count,XMFLOAT3 position,XMFLOAT3 rotation):name(dotMatrixName),vertex(count),position(position),rotation(rotation){}
    void DotMatrix::handleDotMatrix1(XMFLOAT3 Rotation){
        VirtualGPU::dotRotation(this->vertex,Rotation,this->position);
    }

    // 按照index插入到vertex顶点表中。插入的点的坐标是以原点为参考的，实际保存的点是以中心点为参考的
    void DotMatrix::InsertVertex(int index,XMFLOAT3 newVertex){
        if (this->vertex.size()<=index){
            this->vertex.push_back(XMFLOAT3(0.0f,0.0f,0.0f));
            InsertVertex(index,newVertex);
        }
        newVertex.x+=position.x;
        newVertex.y+=position.y;
        newVertex.z+=position.z;
        VirtualGPU::rotateSingleDot(newVertex,this->rotation,position);
        this->vertex[index]=newVertex;
    }
    void DotMatrix::InsertMesh(int index1,int index2,int index3){
        auto indexMax=this->vertex.size()-1;
        if (index1>indexMax||index2>indexMax||index3>indexMax){
            throw "index out of range";
            return;
        }
        this->mesh.push_back(Mesh(index1,index2,index3));
    }
    // 生成一个正方体
    DotMatrix GenerateNewMesh1(){
        DotMatrix newRectangle("cube",8,XMFLOAT3(0,300,0));
        newRectangle.InsertVertex(0,XMFLOAT3(-100, 100, 100));   // 前上左
        newRectangle.InsertVertex(1,XMFLOAT3(100, 100, 100));    // 前上右
        newRectangle.InsertVertex(2,XMFLOAT3(-100, -100, 100));  // 前下左
        newRectangle.InsertVertex(3,XMFLOAT3(-100, -100, -100)); // 后下左
        newRectangle.InsertVertex(4,XMFLOAT3(-100, 100, -100));  // 后上左
        newRectangle.InsertVertex(5,XMFLOAT3(100, 100, -100));   // 后上右
        newRectangle.InsertVertex(6,XMFLOAT3(100, -100, 100));   // 前下右
        newRectangle.InsertVertex(7,XMFLOAT3(100, -100, -100));  // 后下右
        
        // 前面 (Z正方向)
        newRectangle.InsertMesh(0,1,2);  // 前面三角形1
        newRectangle.InsertMesh(1,6,2);  // 前面三角形2
        
        // 后面 (Z负方向)
        newRectangle.InsertMesh(4,3,5);  // 后面三角形1
        newRectangle.InsertMesh(3,7,5);  // 后面三角形2
        
        // 上面 (Y正方向)
        newRectangle.InsertMesh(0,4,1);  // 上面三角形1
        newRectangle.InsertMesh(1,4,5);  // 上面三角形2
        
        // 下面 (Y负方向)
        newRectangle.InsertMesh(2,6,3);  // 下面三角形1
        newRectangle.InsertMesh(3,6,7);  // 下面三角形2
        
        // 左面 (X负方向)
        newRectangle.InsertMesh(0,2,4);  // 左面三角形1
        newRectangle.InsertMesh(2,3,4);  // 左面三角形2
        
        // 右面 (X正方向)
        newRectangle.InsertMesh(1,5,6);  // 右面三角形1
        newRectangle.InsertMesh(5,7,6);  // 右面三角形2
        
        return newRectangle;
    }
    // 找到model文件夹中的第一个obj文件进行解析,gpt生成，逻辑混乱，不能保证是否有效。
    DotMatrix AnalysisModel(){
        std::string modelPath = "C:\\workspace\\learn\\render\\model"; // 模型文件夹路径
        std::string objFilePath = "";
        
        // 查找第一个 .obj 文件
        WIN32_FIND_DATAW findFileData;
        std::wstring wModelPath = std::wstring(modelPath.begin(), modelPath.end()) + L"\\*.obj";
        HANDLE hFind = FindFirstFileW(wModelPath.c_str(), &findFileData);
        
        if (hFind != INVALID_HANDLE_VALUE) {
            // 将宽字符文件名转换回窄字符
            char cFileName[MAX_PATH];
            WideCharToMultiByte(CP_ACP, 0, findFileData.cFileName, -1, cFileName, MAX_PATH, NULL, NULL);
            objFilePath = modelPath + "\\" + cFileName;
            FindClose(hFind);
        } else {
            // 如果没有找到 obj 文件，返回一个默认的立方体
            return GenerateNewMesh1();
        }
        // 解析 OBJ 文件
        std::vector<XMFLOAT3> vertices;
        std::vector<std::tuple<int, int, int>> faces;
        
        std::ifstream file(objFilePath);
        if (!file.is_open()) {
            // 如果无法打开文件，返回默认立方体
            return GenerateNewMesh1();
        }
        std::string line;
        while (std::getline(file, line)) {
            std::istringstream iss(line);
            std::string prefix;
            iss >> prefix;
            
            if (prefix == "v") {
                // 处理顶点
                float x, y, z;
                iss >> x >> y >> z;
                vertices.push_back(XMFLOAT3(x, y, z));
            } else if (prefix == "f") {
                // 处理面（只处理顶点索引，忽略纹理和法线索引）
                std::string v1, v2, v3;
                iss >> v1 >> v2 >> v3;
                
                // 提取顶点索引（OBJ索引从1开始，需要减1）
                int idx1 = std::stoi(v1.substr(0, v1.find('/'))) - 1;
                int idx2 = std::stoi(v2.substr(0, v2.find('/'))) - 1;
                int idx3 = std::stoi(v3.substr(0, v3.find('/'))) - 1;
                
                faces.push_back(std::make_tuple(idx1, idx2, idx3));
            }
        }
        file.close();
        // 创建DotMatrix对象并填充数据
        char cFileName[MAX_PATH];
        WideCharToMultiByte(CP_ACP, 0, findFileData.cFileName, -1, cFileName, MAX_PATH, NULL, NULL);
        // 第一个调整位置，第二个调整朝向。
        DotMatrix model(cFileName, vertices.size(), XMFLOAT3(0, 600, -500),XMFLOAT3(270.0f,0.0f,0.0f));
        // 插入所有顶点
        for (size_t i = 0; i < vertices.size(); i++) {
            vertices[i].x*=1000;
            vertices[i].y*=1000;
            vertices[i].z*=1000;
            model.InsertVertex(i, vertices[i]);
        }
        // 插入所有面
        for (const auto& face : faces) {
            model.InsertMesh(std::get<0>(face), std::get<1>(face), std::get<2>(face));
        }
        
        return model;
    }
}